package com.fpx.open.platform.common.util;

import java.io.IOException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fpx.open.platform.common.constant.BaseConstant;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


/**
 * 加密解密工具类
 * @author sunkey
 * @date Mar 25, 2013 11:13:47 AM
 * @version 1.0.0 
 * @copyright fpx.com 
 */
@SuppressWarnings("restriction")
public class Cryptogram {
	
	private final static Logger logger = LoggerFactory.getLogger(Cryptogram.class);

	private final static int keyLength = 16;
	
	//16位
	public final static String AES_SECRET_KEY = "W*D3f{~/dUv[0bZX";
	
	/** 密文{算法/模式/补码方式} */
	private final static String CIPHER = "AES/CBC/PKCS5Padding";
	
	private final static Key key = createKey(AES_SECRET_KEY);

	private final static char[] ivArr = { 'Q', 'H', 'h', 'I', 's', 'k', 's',
			'F', '&', '8', 'I', 'a', 'j', '9', 't', 'M' };
	
	/**
	 * BASE64加密
	 * 
	 * @param arg0
	 * @return
	 */
	public static String encryptBASE64(byte[] arg0) {
		return (new BASE64Encoder()).encodeBuffer(arg0);
	}

	/**
	 * BASE64解密
	 * 
	 * @param arg0
	 * @return
	 */
	public static byte[] decodeBASE64(String arg0) {
		try {
			return (new BASE64Decoder()).decodeBuffer(arg0);
		} catch (IOException e) {
			logger.warn(e.getMessage(), e);
			return null;
		}
	}

	/**
	 * 创建密钥
	 * @param secretKey 密钥
	 * @return
	 */
	public static Key createKey(String secretKey) {
		byte[] keyByte = new byte[keyLength];
		Key key = null;

		try {
			if (secretKey == null || secretKey.isEmpty()) {
				secretKey = "0sB-L0+51P16zcdOL+Mf1N9Q@S*MnklW";
			}
			
			byte[] inputKey = secretKey.getBytes("UTF-8");
			inputKey = encryptSHA256(inputKey);
			if (inputKey.length < keyLength) {
				byte tempbyte[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
						0, 0, 0, 0, 0, 0, 0, 0, 0 };
				System.arraycopy(inputKey, 0, keyByte, 0, inputKey.length);
				System.arraycopy(tempbyte, 0, keyByte, inputKey.length,
						keyByte.length - inputKey.length);
			} else if (inputKey.length > keyLength) {
				System.arraycopy(inputKey, 0, keyByte, 0, keyLength);
			} else {
				System.arraycopy(inputKey, 0, keyByte, 0, inputKey.length);
			}
			SecretKeySpec KeySpec = new SecretKeySpec(keyByte, "AES");
			key = KeySpec;

		} catch (Exception e) {
			logger.warn(e.getMessage(), e);
		}
		return key;
	}

	/**
	 * AES加密
	 * @param str 被加密串
	 * @param secretkey 密钥
	 * @return
	 */
	public static String encryptAES(String str, String secretKey) {
		
		
		try {
			byte[] ivBytes = String.valueOf(ivArr).getBytes("UTF-8");
			IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
			Cipher cipher = Cipher.getInstance(CIPHER);
			if(secretKey != null){
				Key key = createKey(secretKey);
				cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
			}else{//默认
				cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
			}
			byte[] encrypted = cipher.doFinal(str.getBytes());
			return encryptBASE64(encrypted).trim();
		} catch (Exception e) {
			logger.warn(e.getMessage(), e);
			return null;
		}
	}

	/**
	 * AES解密
	 * 
	 * @param encryptStr 密串
	 * @param secretkey 密钥
	 * @return
	 */

	public static String decryptAES(String encryptStr, String secretKey) {
		byte[] tmp = decodeBASE64(encryptStr);
		try {
			byte[] ivBytes = String.valueOf(ivArr).getBytes(BaseConstant.ENCODE_TYPE);
			IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
			Cipher cipher = Cipher.getInstance(CIPHER);
			if(secretKey != null){
				Key key = createKey(secretKey);
				cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
			}else{//默认
				cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
			}
			
			byte[] decrypted = cipher.doFinal(tmp);
			return new String(decrypted);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return null;
		}
	}

	/**
	 * SHA256加密
	 * @param data 
	 * @return
	 * @throws Exception
	 */
	private static byte[] encryptSHA256(byte[] data) {
		MessageDigest sha;

		try {
			sha = MessageDigest.getInstance("SHA-256");
			sha.update(data);
			return sha.digest();
		} catch (NoSuchAlgorithmException e) {
			logger.error(e.getMessage(), e);
			return null;
		}
	}

	/**
	 * 处理后的SHA方式加密，不可逆
	 * @param 被加密串
	 */
	public static String encryBySHA(String str) {
		return encryptBASE64(encryptSHA256(str.getBytes())).trim();
	}

	/**
	 * 根据默认密钥进行字符串加密
	 * 
	 * @param orignString  被加密串
	 * @return 密串
	 */
	public static String encrypt(String orignString) {
		String str = encryptAES(orignString, null);
		int index = str.indexOf("\r\n");
		if (str.indexOf("\r\n") != -1) {
			str = str.substring(0, index);
		}
		return str;
	}

	/**
	 * 根据secretKey密钥进行字符串加密
	 * @param origString 被加密串
	 * @param secretKey 密钥
	 * @return 密串
	 */
	public static String encrypt(String origString, String secretKey) {
		String str = encryptAES(origString, secretKey);
		int index = str.indexOf("\r\n");
		if (str.indexOf("\r\n") != -1) {
			str = str.substring(0, index);
		}
		return str;
	}

	/**
	 * 根据默认密钥进行字符串解密
	 * @param orignString 解密字符串
	 * @return String 被加密串
	 */
	public static String decrypt(String origString) {
		String str = decryptAES(origString, null);
		int index = str.indexOf("\r\n");
		if (str.indexOf("\r\n") != -1) {
			str = str.substring(0, index);
		}
		return str;
	}

	/**
	 * 根据secretKey密钥进行字符串解密
	 * @param orignString 解密字符串
	 * @param secretKey 密钥
	 * @return String 被加密串
	 */
	public static String decrypt(String orignString, String secretKey) {
		String str = decryptAES(orignString, secretKey);
		int index = str.indexOf("\r\n");
		if (str.indexOf("\r\n") != -1) {

			str = str.substring(0, index);
		}
		return str;
	}

}
